package com.zf.developaccumulate.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 网络文件下载
 */
@Slf4j
public class NetFileDownloadUtils {
    public static void main(String[] args) throws IOException {
        // String url = "https://cdn.bootcdn.net/ajax/libs/vue/3.4.33/vue.cjs.js";
        String url = "https://www.ghxi.com/wp-content/uploads/2019/12/2020logo.png";
        String filename = "2020logo.png";

        // byte[] fileBytes = downloadNetFileByUrlConnection(url, HttpMethod.GET, null);
        // FileCopyUtils.copy(fileBytes, new File("D:\\" + filename));

        byte[] fileByte2 = downloadNetFileByRestTemplate(url, HttpMethod.GET, null);
        FileCopyUtils.copy(fileByte2, new File("D:\\" + filename));
    }


    /**
     * 下载网络文件；使用 HttpURLConnection 实现
     */
    public static byte[] downloadNetFileByUrlConnection(String fileUrl, HttpMethod httpMethod, HttpHeaders headers) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法
        connection.setRequestMethod(httpMethod.name());
        // 设置连接超时为5秒
        connection.setConnectTimeout(5 * 1000);
        // 设置读取超时为100秒
        connection.setReadTimeout(100 * 1000);
        //设置一个默认的UA，如果 HttpHeaders 中传递了新的UA，则会覆盖默认值
        connection.setRequestProperty(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0");

        // 设置请求头
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
                connection.setRequestProperty(entry.getKey(), String.join(",", entry.getValue()));
            }
        }

        // 存放响应体
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        // 获取响应码
        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) { // 成功
            // 获取响应头
            Map<String, List<String>> headerFields = connection.getHeaderFields();

            // 获取响应体输入流
            InputStream inputStream = connection.getInputStream();
            // 读取流中的内容
            FileCopyUtils.copy(inputStream, outputStream);
        } else {
            // 失败
            log.warn("下载失败");
            return new byte[0];
        }
        // 关闭连接
        connection.disconnect();
        // 返回响应体的内容
        return outputStream.toByteArray();
    }

    /**
     * 下载网络文件；使用 RestTemplate 实现
     */
    public static byte[] downloadNetFileByRestTemplate(String fileUrl, HttpMethod httpMethod, HttpHeaders headers) {
        // 创建请求工厂
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        // 设置连接超时为5秒
        requestFactory.setConnectTimeout(5 * 1000);
        // 设置读取超时为100秒
        requestFactory.setReadTimeout(100 * 1000);
        // RestTemplate 默认没有连接和读取超时限制
        RestTemplate restTemplate = new RestTemplate(requestFactory);

        // 如果没有UA，则设置一个默认的UA
        headers = Optional.ofNullable(headers).orElse(new HttpHeaders());
        if (!headers.containsKey(HttpHeaders.USER_AGENT)) {
            headers.add(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0");
        }

        HttpEntity<Object> httpEntity = new HttpEntity<>(null, headers);
        // 发送请求
        ResponseEntity<byte[]> exchange = restTemplate.exchange(fileUrl, httpMethod, httpEntity, byte[].class);

        // 获取结果
        if (exchange.getStatusCode() == HttpStatus.OK) {
            // 成功，返回响应
            return exchange.getBody();
        } else {
            // 失败
            log.warn("下载失败");
            return new byte[0];
        }
    }
}
